const axios = require('axios');
const fs = require('fs-extra');
const path = require('path');
const FormData = require('form-data');

// 基础URL配置
const BASE_URL = 'http://localhost:3000/api';
const AUTH_URL = `${BASE_URL}/auth`;
const MODEL_URL = `${BASE_URL}/models`;

// 测试用户凭据
const TEST_USER = {
    username: 'admin',
    password: '123456',
    email: '525675049@qq.com'
};

// 全局变量
let accessToken = '';
let testModelId = '';
let uploadedFileId = '';

// 控制台日志颜色
const colors = {
    reset: '\x1b[0m',
    green: '\x1b[32m',
    red: '\x1b[31m',
    yellow: '\x1b[33m',
    blue: '\x1b[34m',
    magenta: '\x1b[35m'
};

// 测试文件路径
const TEST_MODEL_PATH = path.join(__dirname, 'test_model.glb');

/**
 * 格式化日志输出
 */
function logSection(title) {
    console.log(`\n${colors.magenta}===== ${title} =====${colors.reset}`);
}

function logSuccess(message) {
    console.log(`${colors.green}✅ ${message}${colors.reset}`);
}

function logError(message, error) {
    console.log(`${colors.red}❌ ${message}${colors.reset}`);
    if (error.response) {
        console.log(`状态码: ${error.response.status}`);
        console.log(`错误信息:`, error.response.data);
    } else if (error.request) {
        console.log('无法连接到服务器，请确保服务器正在运行');
    } else {
        console.log(`请求错误: ${error.message}`);
    }
}

function logInfo(message) {
    console.log(`${colors.blue}ℹ️ ${message}${colors.reset}`);
}

/**
 * 创建测试模型文件
 */
async function createTestModelFile() {
    logSection('创建测试模型文件');

    try {
        // 创建一个简单的文本文件作为测试模型文件
        // 注：在实际测试中，这应该是一个真实的3D模型文件（如GLB、OBJ或STL）
        await fs.writeFile(TEST_MODEL_PATH, 'This is a placeholder for a 3D model file');
        logSuccess('测试模型文件创建成功');
        return true;
    } catch (error) {
        console.error('创建测试模型文件失败:', error);
        return false;
    }
}

/**
 * 清理测试模型文件
 */
async function cleanupTestFiles() {
    logSection('清理测试文件');

    try {
        if (await fs.pathExists(TEST_MODEL_PATH)) {
            await fs.unlink(TEST_MODEL_PATH);
            logSuccess('测试模型文件清理成功');
        }
        return true;
    } catch (error) {
        console.error('清理测试文件失败:', error);
        return false;
    }
}

/**
 * 注册测试用户
 */
async function registerTestUser() {
    logSection('注册测试用户');

    try {
        await axios.post(`${AUTH_URL}/register`, TEST_USER);
        logSuccess(`用户 "${TEST_USER.username}" 注册成功`);
        return true;
    } catch (error) {
        if (error.response && error.response.status === 409) {
            logInfo(`用户 "${TEST_USER.username}" 已存在，继续测试`);
            return true;
        }
        logError('注册测试用户失败', error);
        return false;
    }
}

/**
 * 登录测试用户
 */
async function loginTestUser() {
    logSection('登录测试用户');

    try {
        const response = await axios.post(`${AUTH_URL}/login`, {
            username: TEST_USER.username,
            password: TEST_USER.password
        });

        accessToken = response.data.data.token;
        logSuccess(`用户 "${TEST_USER.username}" 登录成功`);
        logInfo(`访问令牌: ${accessToken.substring(0, 15)}...`);
        return true;
    } catch (error) {
        logError('登录测试用户失败', error);
        return false;
    }
}

/**
 * 创建测试模型
 */
async function createTestModel() {
    logSection('创建测试模型');

    const modelData = {
        name: '文件测试模型',
        description: '这是一个用于文件操作测试的3D模型'
    };

    try {
        const response = await axios.post(MODEL_URL, modelData, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        testModelId = response.data.data.modelId;
        logSuccess('创建测试模型成功');
        logInfo(`模型ID: ${testModelId}`);
        return true;
    } catch (error) {
        logError('创建测试模型失败', error);
        return false;
    }
}

/**
 * 测试上传模型文件
 */
async function testUploadModelFile() {
    logSection('测试上传模型文件');

    if (!testModelId) {
        logError('无法上传文件，模型ID不存在');
        return false;
    }

    try {
        const formData = new FormData();
        formData.append('file', fs.createReadStream(TEST_MODEL_PATH), {
            filename: 'test_model.glb',
            contentType: 'application/octet-stream'
        });

        const response = await axios.post(
            `${MODEL_URL}/${testModelId}/upload`,
            formData,
            {
                headers: {
                    Authorization: `Bearer ${accessToken}`,
                    ...formData.getHeaders()
                }
            }
        );

        uploadedFileId = response.data.data.fileId;
        logSuccess('上传模型文件成功');
        logInfo(`文件大小: ${response.data.data.fileSize}`);
        console.log('响应数据:', response.data);
        return true;
    } catch (error) {
        logError('上传模型文件失败', error);
        return false;
    }
}

/**
 * 测试下载模型文件
 */
async function testDownloadModelFile() {
    logSection('测试下载模型文件');

    if (!testModelId) {
        logError('无法下载文件，模型ID不存在');
        return false;
    }

    try {
        const response = await axios.get(
            `${MODEL_URL}/${testModelId}/download`,
            {
                headers: { Authorization: `Bearer ${accessToken}` },
                responseType: 'arraybuffer'
            }
        );

        const downloadPath = path.join(__dirname, 'downloaded_model.glb');
        await fs.writeFile(downloadPath, response.data);
        logSuccess('下载模型文件成功');
        logInfo(`下载文件保存至: ${downloadPath}`);

        // 清理下载的文件
        if (await fs.pathExists(downloadPath)) {
            await fs.unlink(downloadPath);
            logInfo('清理下载的文件');
        }

        return true;
    } catch (error) {
        logError('下载模型文件失败', error);
        return false;
    }
}

/**
 * 测试下载不同格式的模型文件
 */
async function testDownloadDifferentFormat() {
    logSection('测试下载不同格式的模型文件');

    if (!testModelId) {
        logError('无法下载文件，模型ID不存在');
        return false;
    }

    try {
        const response = await axios.get(
            `${MODEL_URL}/${testModelId}/download?format=obj`,
            {
                headers: { Authorization: `Bearer ${accessToken}` },
                responseType: 'arraybuffer'
            }
        );

        const downloadPath = path.join(__dirname, 'downloaded_model.obj');
        await fs.writeFile(downloadPath, response.data);
        logSuccess('下载OBJ格式模型文件成功');
        logInfo(`下载文件保存至: ${downloadPath}`);

        // 清理下载的文件
        if (await fs.pathExists(downloadPath)) {
            await fs.unlink(downloadPath);
            logInfo('清理下载的文件');
        }

        return true;
    } catch (error) {
        logError('下载OBJ格式模型文件失败', error);
        return false;
    }
}

/**
 * 测试获取模型缩略图
 */
async function testGetModelThumbnail() {
    logSection('测试获取模型缩略图');

    if (!testModelId) {
        logError('无法获取缩略图，模型ID不存在');
        return false;
    }

    try {
        const response = await axios.get(
            `${MODEL_URL}/${testModelId}/thumbnail`,
            {
                headers: { Authorization: `Bearer ${accessToken}` }
            }
        );

        logSuccess('获取模型缩略图成功');
        console.log('响应数据:', {
            status: response.data.status,
            thumbnailLength: response.data.data.thumbnail.length.toString().substring(0, 20) + '...'
        });

        // 验证是否为有效的Base64图像
        const base64Data = response.data.data.thumbnail;
        if (base64Data.startsWith('data:image')) {
            logSuccess('缩略图数据格式正确');
        } else {
            logError('缩略图格式不正确');
        }

        return true;
    } catch (error) {
        logError('获取模型缩略图失败', error);
        return false;
    }
}

/**
 * 删除测试模型
 */
async function deleteTestModel() {
    logSection('删除测试模型');

    if (!testModelId) {
        logError('无法删除模型，模型ID不存在');
        return false;
    }

    try {
        const response = await axios.delete(`${MODEL_URL}/${testModelId}`, {
            headers: { Authorization: `Bearer ${accessToken}` }
        });

        logSuccess('删除测试模型成功');
        console.log('响应数据:', response.data);
        return true;
    } catch (error) {
        logError('删除测试模型失败', error);
        return false;
    }
}

/**
 * 运行所有测试
 */
async function runAllTests() {
    console.log(`${colors.yellow}==============================${colors.reset}`);
    console.log(`${colors.yellow}开始文件操作接口测试${colors.reset}`);
    console.log(`${colors.yellow}==============================${colors.reset}`);

    try {
        // 创建测试文件
        await createTestModelFile();

        // 用户认证
        if (!(await registerTestUser())) return;
        if (!(await loginTestUser())) return;

        // 创建测试模型
        if (!(await createTestModel())) return;

        // 文件操作测试
        if (!(await testUploadModelFile())) return;
        if (!(await testDownloadModelFile())) return;
        if (!(await testDownloadDifferentFormat())) return;
        if (!(await testGetModelThumbnail())) return;

        // 清理
        await deleteTestModel();
        await cleanupTestFiles();

        console.log(`\n${colors.green}==============================${colors.reset}`);
        console.log(`${colors.green}文件操作接口测试完成${colors.reset}`);
        console.log(`${colors.green}==============================${colors.reset}`);
    } catch (error) {
        console.error(`${colors.red}测试过程中发生错误:${colors.reset}`, error);
    }
}

// 执行测试
runAllTests(); 